<template>
	<view class="content">
		<view class="onlineBox">
			<p>在线人数: 共{{memberList.length}}人</p>

			<view v-for="item in memberList" :key="item.id" :class="['infoBox',item.isReady ?'start':'']">
				<text>用户ID: {{item.data.userNo}}</text>
				<text>用户名: {{item.data.userName}}</text>
			</view>
		</view>
		<view class="msgBox">
			<ul class="textBox" id="textBox">
				<li v-for="(item,index) in msgList" :key="index">
					{{item.name}}:
					{{item.data}} -
					{{item.time}}
				</li>
			</ul>
			<view class="inputBox">
				<u-input placeholder="请输入要发送的消息" v-model="msgValue"></u-input>
			</view>
			<view class="btnBox">
				<u-button type="primary" @click="handleSend">发送</u-button>
				<u-button type="success" @click="handleReady">{{isReady?'取消准备':'准备'}}</u-button>
				<u-button type="error" @click="handleLogout">退出</u-button>
			</view>
		</view>

	</view>
</template>

<script lang="ts" setup>
	import { ref, onMounted, onBeforeUnmount } from 'vue'
	import goEasy from '@/utils/websocket'

	// 云对象
	const ddzUser = uniCloud.importObject('ddz-user')
	const ddzGame = uniCloud.importObject('ddz-game')
	// 页面变量
	const isReady = ref<boolean>(false)
	const memberList = ref<any>([])
	const msgList = ref<any>([])
	const msgValue = ref<string>('')
	let user = ref<any>({
		userInfo: {},
		score: {}
	})

	onMounted(() => {
		user.value.userInfo = uni.getStorageSync('user')
		user.value.score = uni.getStorageSync('score')

		// 初始化websocket
		initWebSocket()


	})
	onBeforeUnmount(async () => {
		console.log('退出前')
		// 断开连接
		goEasy.disconnect({
			onSuccess: function () {
				console.log("GoEasy 断开连接.")
			},
			onFailed: function (error) {
				console.log("断开连接Failed" + error.code + ",error:" + error.content);
			}
		});

		let uid = user.value.userInfo._id
		await ddzUser.logoutUser(uid)
		// console.log(res);
	})
	const initWebSocket = () => {
		// 初始化websocket
		let id = user.value.userInfo._id;
		let userNo = user.value.userInfo.userNo;
		let userName = user.value.userInfo.userName;
		let channel = "test_channel";
		// 连接
		goEasy.connect({
			id,
			data: { userNo, userName },
			onSuccess: async () => {
				msgList.value.push({
					name: userName,
					data: '连接服务器成功！',
					time: dateFormat(Date.now())
				})
				console.log("GoEasy connect successfully.")
			},
			onFailed: (error) => {
				console.log("Failed to connect GoEasy, code:" + error.code + ",error:" + error.content);
			}
		});
		// 订阅消息
		goEasy.pubsub.subscribe({
			channel,
			presence: {
				enable: true
			},
			onMessage: (message) => {
				// 根据type 1聊天 2准备 3出牌
				console.log('goEasy新消息', message);
				const content = JSON.parse(message.content);
				receiveChat(content);
				if (content.type == 'ready') {
					receiveStart(content);
				} else if (content.type == 'start') {
					handleStart(content)
				}
			},
			onSuccess: () => {

			},
			onFailed: (error) => {
				console.log('goEasy错误消息', error)
			}
		});
		// 监听成员上下线
		goEasy.pubsub.subscribePresence({
			channel,
			membersLimit: 10,
			onPresence: function (presenceEvent) {
				console.log("监听上下线 ", presenceEvent);
				if (presenceEvent.member.id == id) return // 自己的信息就不做处理
				memberList.value = presenceEvent.members; // 刷新在线成员列表
			},
			onSuccess: function () {  //监听成功
				console.log("监听上下线successfully.");
			},
			onFailed: function (error) { //监听失败
				console.log("监听上下线Failed" + error.code + ",error:" + error.content);
			},
		});
		// 查询在线成员
		goEasy.pubsub.hereNow({
			channel,
			limit: 10,
			onSuccess: function (response) {
				console.log("查询在线 ", response);
				// 刷新在线成员列表
				getReadyState(response.content.members);
			},
			onFailed: function (error) { //获取失败
				console.log("查询在线Failed" + error.code + ",error:" + error.content);
			}
		});
	}
	const scrollBottom = () => {
		uni.createSelectorQuery().select('#textBox').boundingClientRect((res) => {
			console.log(res)
		})
	}
	// 用户登录后 获取在线成员的准备状态
	const getReadyState = async (members : any) => {
		let id = user.value.userInfo._id;
		if (members.length == 1 && members[0].id == id) {
			// 当前只有自己在线
			await ddzGame.clearOnlineTemp();
		} else {
			const res = await ddzGame.getOnlineTemp();
			console.log(res)
			members = setOnlineReady(members, res.data.data)
		}
		await ddzGame.addOnlineTemp(id)
		console.log(members)
		memberList.value = members;
	}
	// 根据条件 设置已在线角色的准备状态
	const setOnlineReady = (list, readyList) => {
		return list.map(item => {
			let res = readyList.find(m => m.uid == item.id)
			if (!res) return item
			return {
				...item,
				isReady: res.isReady
			}
		})
	}
	// 点击准备事件
	const handleReady = async () => {
		let data = isReady.value ? ' 取消准备' : '准备好了';
		let name = user.value.userInfo.userName;
		let id = user.value.userInfo._id;
		let readyState = !isReady.value
		const res = await ddzUser.sendMsg(JSON.stringify({
			id,
			name,
			data,
			type: 'ready',
			isReady: readyState,
			time: Date.now()
		}))
		console.log('发送消息', res);
		await ddzGame.updateOnlineTemp(id, readyState);

	}

	// 点击发送事件
	const handleSend = async () => {
		let data = msgValue.value;
		let name = user.value.userInfo.userName;
		let id = user.value.userInfo._id;
		const res = await ddzUser.sendMsg(JSON.stringify({
			id,
			name,
			data,
			type: 'chat',
			time: Date.now()
		}))
		console.log('发送消息', res);
		msgValue.value = '';
	}
	// 处理接收 类型是普通消息
	const receiveChat = (content : any) => {
		// console.log(content)
		msgList.value.push({
			name: content.name,
			data: content.data,
			time: dateFormat(content.time)
		})
	}
	// 处理接收 类型是准备
	const receiveStart = (content : any) => {
		// console.log(content);
		if (content.id == user.value.userInfo._id) {
			// 自己
			isReady.value = content.isReady;
		}
		let newMemberList = memberList.value;
		newMemberList.forEach(m => {
			if (m.id == content.id) {
				m.isReady = content.isReady;
			}
		})
		memberList.value = newMemberList;
	}
	// 处理接受 类型是开始游戏
	const handleStart = (content) => {
		const id = user.value.userInfo._id;
		
		content.userList.forEach(item => {
			if (item.uid == id && item.isReady) {
				uni.showLoading({
					title: '进入游戏中。。。'
				})
				
				setTimeout(() => {
					uni.hideLoading();
					uni.navigateTo({
						url: '/pages/ddzGame/ddzGame'
					})
				}, 2000)
			}
		})
	}

	const handleClick = async () => {
		// 删除所有表
		await ddzUser.delUser()
	}
	const handleLogout = async () => {
		// 登出功能
		const id = user.value.userInfo._id;
		await ddzGame.delOnlineTemp(id)
		uni.removeStorageSync('score')
		uni.reLaunch({
			url: '/pages/login/login'
		})
	}
	const dateFormat = (time : number) => {
		let date = new Date(time);
		let year = date.getFullYear();
		// 在日期格式中，月份是从0开始的，因此要加0，使用`三元表达式在小于10的前面加0，以达到格式统一  如 09:11:05
		let month = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;
		let day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
		let hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
		let minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
		let seconds = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
		// 拼接
		return year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds;
		// return year + "-" + month + "-" + day;
	}
</script>

<style lang="scss" scoped>
	.content {
		width: 100vw;
		height: 100vh;
		display: flex;
	}

	.onlineBox {
		height: 100vh;
		width: 200px;
		padding: 10px;

		.infoBox {
			border-bottom: 1px solid #ddd;

			text {
				display: block;
				white-space: nowrap;
				overflow: hidden;
				text-overflow: ellipsis;
			}
		}

		.start {
			background-color: lightgreen;
		}
	}

	.msgBox {
		height: 100vh;
		flex: 1;
		display: flex;
		flex-direction: column;

		.textBox {
			border: 1px solid #DDD;
			width: 100%;
			flex: 1;
			overflow: scroll;
		}

		.btnBox {
			width: 100%;
			height: 50px;
			display: flex;
			align-items: center;
		}
	}
</style>